package com.dongnam.quanly.web.audit;

import java.sql.Timestamp;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dongnam.quanly.common.ActionCategory;
import com.dongnam.quanly.common.ActionType;
import com.dongnam.quanly.common.ObjectType;
import com.dongnam.quanly.common.ScreenId;
import com.dongnam.quanly.common.dao.AuditTrailLogDao;
import com.dongnam.quanly.common.model.AuditTrailLog;
import com.dongnam.quanly.common.persistence.HibernateUtil;
import com.dongnam.quanly.web.JSFUtility;
import com.dongnam.quanly.web.UserBean;

public class AuditLogger {

	private static Logger logger = LoggerFactory.getLogger(AuditLogger.class);

	private static final int DEFAULT_CAUSE_LEN = 100;
	private static final int DEFAULT_ORIGIN_LEN = 300;
	private static final int DEFAULT_NEW_LEN = 300;
	private static final int DEFAULT_OBJECTID_LEN = 100;

	/**
	 * Create a new transaction to log audit trail
	 */
	public static void logAuditTrail(ScreenId screenId, ActionCategory category, ActionType actionType,
			boolean success, ObjectType object, String objectId, String cause, String oldVal, String newVal) {
		Session session = HibernateUtil.startCurrentSession();
		try {
			persistAuditTrail(screenId, category, actionType, success, object, objectId, cause, oldVal, newVal);
			session.getTransaction().commit();
			logger.debug("logged. screenId: {}, actionType: {}", screenId, actionType);
		} catch (Exception e) {
			logger.debug("Excetion: ", e);
			logger.error(
					"Cannot log audit trail, screenId={}, category={}, actionType={}, success={}, object={}, objectId={}",
					new Object[] { screenId, category, actionType, success, object, objectId });
			session.getTransaction().rollback();
		}
	}

	public static void persistAuditTrail(ScreenId screenId, ActionCategory category, ActionType actionType,
			boolean success, ObjectType object, String objectId, String cause, String oldVal, String newVal) {
		AuditTrailLog log = new AuditTrailLog();
		HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance()
				.getExternalContext().getRequest();
		String actioneeIp = httpServletRequest.getRemoteAddr();
		UserBean userBean = (UserBean) JSFUtility.findBean(UserBean.class);
		if (userBean.getUser() == null)
			log.setActioneeName("UN-LOGGEDIN");
		else
			log.setActioneeName(userBean.getUser().getUserId());
		log.setActionTime(new Timestamp(System.currentTimeMillis()));
		log.setScreenId(screenId);
		log.setActionCategory(category);
		log.setActioneeIp(actioneeIp);
		log.setActionType(actionType);
		log.setResult(success ? "SUCCESS" : "FAILED");
		log.setObject(object);
		if (objectId != null && objectId.length() > DEFAULT_OBJECTID_LEN) {
			objectId = objectId.substring(0, DEFAULT_OBJECTID_LEN - 4) + "...";
		}
		log.setObjectId(objectId);
		if (cause != null && cause.length() > DEFAULT_CAUSE_LEN) {
			logger.warn("Value too long for cause: {}", cause);
			cause = cause.substring(0, DEFAULT_CAUSE_LEN - 4) + "...";
		}
		log.setCause(success ? null : cause);
		// if (success && (oldVal != null && newVal != null)) {
		if (oldVal != null && oldVal.length() > DEFAULT_ORIGIN_LEN) {
			logger.warn("Value too long for origin value: {}", oldVal);
			oldVal = oldVal.substring(0, DEFAULT_ORIGIN_LEN - 4) + "...";
		}
		log.setOriginVal(oldVal == null ? "" : oldVal);
		if (newVal != null && newVal.length() > DEFAULT_NEW_LEN) {
			logger.warn("Value too long for updated value: {}", newVal);
			newVal = newVal.substring(0, DEFAULT_NEW_LEN - 4) + "...";
		}
		log.setNewVal(newVal == null ? "" : newVal);
		// }
		// log.setDetails(prefix + String.format(details, args));
		new AuditTrailLogDao().makePersistent(log);
	}

}
